﻿namespace Mercury.ParticleEngine
{
    using System;
    using System.Diagnostics.Contracts;

    public static class SingleExtensions
    {
        [Pure]
        public static Boolean IsFinite(this Single instance)
        {
            return !Single.IsInfinity(instance) &&
                   !Single.IsNaN(instance);
        }

        /// <summary>
        /// Clamps a value so that it falls within a specified range.
        /// </summary>
        /// <param name="value">The value to clamp.</param>
        /// <param name="lower">The minimum permissable value (inclusive).</param>
        /// <param name="upper">The maximum permissable value (inclusive).</param>
        /// <returns>The value, clamped to be within the specified range.</returns>
        static public Single Clamp(this Single value, Single lower, Single upper)
        {
            return Calculator.Clamp(value, lower, upper);
        }

        /// <summary>
        /// Clamps a value so that is falls within a specified range.
        /// </summary>
        /// <param name="value">The value to clamp.</param>
        /// <param name="interval">An interval defining the range of permissable values.</param>
        /// <returns>The value, clamped to be within the specified range.</returns>
        static public Single Clamp(this Single value, IntervalF interval)
        {
            return Calculator.Clamp(value, interval);
        }

        /// <summary>
        /// Wraps a value to within a specified range.
        /// </summary>
        /// <param name="value">The value to be wrapped.</param>
        /// <param name="lower">The lower value.</param>
        /// <param name="upper">The upper value.</param>
        /// <returns>The wrapped value.</returns>
        static public Single Wrap(this Single value, Single lower, Single upper)
        {
            return Calculator.Wrap(value, lower, upper);
        }

        /// <summary>
        /// Wraps a value to be within a specified range.
        /// </summary>
        /// <param name="value">The value to be wrapped.</param>
        /// <param name="interval">An interval defining the range of allowable values.</param>
        /// <returns>The wrapped value.</returns>
        static public Single Wrap(this Single value, IntervalF interval)
        {
            return Calculator.Wrap(value, interval);
        }

        /// <summary>
        /// Calculates the smallest possible epsilon value that avoids floating point rounding
        /// errors when added to the specified value.
        /// </summary>
        /// <param name="value">The value to calculate epsilon for.</param>
        /// <returns>The smallest possible epsilon value that can be added to <paramref name="value"/>
        /// without causing floating point rounding errors.</returns>
        static public Single CalculateEpsilon(this Single value)
        {
            return Calculator.CalculateEpsilon(value);
        }

        /// <summary>
        /// Returns the absolute value of a single precision Single point value.
        /// </summary>
        /// <param name="value">Source value.</param>
        /// <returns>The absolute value of <paramref name="value"/>.</returns>
        static public Single Absolute(Single value)
        {
            return Calculator.Absolute(value);
        }
    }
}